$wgDBminWordLen = 3; # Match this to your MySQL fulltext
$wgDBtransactions = false; # Set to true if using InnoDB tables
+# Change this key to different sequence of 8 bytes, so that sysops cannot
+# obtain the IP addresses of logged-in users.
+$wgIPBlockKey = implode( "", array_map( "chr",
+ array( 57, 100, 182, 241, 93, 122, 40, 195 ) ) );
+
# Turn this on during database maintenance
# $wgReadOnly = true;
# update.php script.
#
-$wgSoftwareRevision = 1001;
+$wgSoftwareRevision = 1002;
?>
ipblocks (IP addresses and users blocked from editing)
-
+ ipb_id
+ Primary key, introduced for privacy.
ipb_address
- Blocked IP address in dotted-quad form or ""
+ Blocked IP address in dotted-quad form or user name.
ipb_user
- Blocked user ID or 0.
+ Blocked user ID or 0 for IP blocks.
ipb_by
User ID who made the block.
ipb_reason
Text comment made by blocker.
-
+ ipb_timestamp
+ Creation (or refresh) date in standard YMDHMS form. IP
+ blocks expire automatically.
+ ipb_auto
+ Indicates that the IP address was banned because a banned
+ user accessed a page through it. If this is 1, ipb_address
+ will be hidden.
random (Random page queue)
<?
# Blocks and bans object
-
+#
#TODO: This could be used everywhere, but it isn't.
-
+#
# All the functions in this class assume the object is either explicitly
-# loaded or filled. It is not load-on-demand.
-
+# loaded or filled. It is not load-on-demand. There are no accessors.
+#
# To use delete(), you only need to fill $mAddress
class Block
{
- var $mAddress, $mUser, $mBy, $mReason, $mTimestamp;
+ var $mAddress, $mUser, $mBy, $mReason, $mTimestamp, $mAuto, $mId;
- function Block( $address = "", $user = "", $by = 0, $reason = "", $timestamp = "" )
+ function Block( $address = "", $user = "", $by = 0, $reason = "",
+ $timestamp = "" , $auto = 0)
{
$this->mAddress = $address;
$this->mUser = $user;
$this->mBy = $by;
$this->mReason = $reason;
$this->mTimestamp = $timestamp;
+ $this->mAuto = $auto;
}
- /*static*/ function newFromDB( $address, $user = 0, $killExpired = true )
- {
+ /*static*/ function newFromDB( $address, $user = 0, $killExpired = true ) {
$ban = new Block();
$ban->load( $address, $user, $killExpired );
return $ban;
}
- function clear()
- {
+ function clear() {
$mAddress = $mReason = $mTimestamp = "";
$mUser = $mBy = 0;
}
# Get a ban from the DB, with either the given address or the given username
- function load( $address, $user = 0, $killExpired = true )
- {
+ function load( $address, $user = 0, $killExpired = true ) {
$fname = "Block::load";
$ret = false;
$killed = false;
if ( 0 == $user ) {
- $sql = "SELECT * FROM ipblocks WHERE ipb_address='$address'";
+ $sql = "SELECT * FROM ipblocks WHERE ipb_address='" . wfStrencode( $address ) . "'";
} else {
- $sql = "SELECT * FROM ipblocks WHERE (ipb_address='$address' OR ipb_user={$user})";
+ $sql = "SELECT * FROM ipblocks WHERE (ipb_address='" . wfStrencode( $address ) .
+ "' OR ipb_user={$user})";
}
-
$res = wfQuery( $sql, $fname );
if ( 0 == wfNumRows( $res ) ) {
$this->initFromRow( $row );
if ( $killExpired ) {
-
# If requested, delete expired rows
do {
$killed = $this->deleteIfExpired();
- $row = wfFetchObject( $res );
+ if ( $killed ) {
+ $row = wfFetchObject( $res );
+ if ( $row ) {
+ $this->initFromRow( $row );
+ }
+ }
} while ( $killed && $row );
# If there were any left after the killing finished, return true
- if ( $row == false ) {
+ if ( !$row ) {
$ret = false;
$this->clear();
} else {
return $ret;
}
- function initFromRow( $row )
- {
+ function initFromRow( $row ) {
$this->mAddress = $row->ipb_address;
$this->mReason = $row->ipb_reason;
$this->mTimestamp = $row->ipb_timestamp;
$this->mUser = $row->ipb_user;
$this->mBy = $row->ipb_by;
+ $this->mAuto = $row->ipb_auto;
+ $this->mId = $row->ipb_id;
}
# Callback with a Block object for every block
- /*static*/ function enumBlocks( $callback, $tag, $killExpired = true )
- {
+ /*static*/ function enumBlocks( $callback, $tag, $killExpired = true ) {
$sql = "SELECT * FROM ipblocks ORDER BY ipb_timestamp";
$res = wfQuery( $sql, "Block::enumBans" );
$block = new Block();
wfFreeResult( $res );
}
- function delete()
- {
- wfQuery( "DELETE FROM ipblocks WHERE ipb_address='{$this->mAddress}'",
- "Block::delete" );
+ function delete() {
+ $fname = "Block::delete";
+ if ( $this->mAddress == "" ) {
+ $sql = "DELETE FROM ipblocks WHERE ipb_id={$this->mId}";
+ } else {
+ $sql = "DELETE FROM ipblocks WHERE ipb_address='" .
+ wfStrencode( $this->mAddress ) . "'";
+ }
+ wfQuery( $sql, "Block::delete" );
}
- function insert()
- {
- $sql = "INSERT INTO ipblocks (ipb_address, ipb_user, ipb_by, " .
- "ipb_reason, ipb_timestamp ) VALUES ('{$this->mAddress}', {$this->mUser}, " .
- "{$this->mBy}, '" . wfStrencode( $this->mReason ) . "','{$this->mTimestamp}')";
+ function insert() {
+ $sql = "INSERT INTO ipblocks
+ (ipb_address, ipb_user, ipb_by, ipb_reason, ipb_timestamp, ipb_auto )
+ VALUES ('" . wfStrencode( $this->mAddress ) . "', {$this->mUser}, {$this->mBy}, '" .
+ wfStrencode( $this->mReason ) . "','{$this->mTimestamp}', {$this->mAuto})";
wfQuery( $sql, "Block::insert" );
}
- function deleteIfExpired()
- {
+ function deleteIfExpired() {
if ( $this->isExpired() ) {
$this->delete();
return true;
}
}
- function isExpired()
- {
+ function isExpired() {
global $wgIPBlockExpiration, $wgUserBlockExpiration;
$period = $this->mUser ? $wgUserBlockExpiration : $wgIPBlockExpiration;
}
}
- function isValid()
- {
+ function isValid() {
return $this->mAddress != "";
}
-
- function updateTimestamp()
- {
- $sql = "UPDATE ipblocks SET ipb_timestamp='" . wfTimestampNow() . "' WHERE ipb_address='{$this->mAddress}'";
+ function updateTimestamp() {
wfQuery( "UPDATE ipblocks SET ipb_timestamp='" . wfTimestampNow() .
- "' WHERE ipb_address='{$this->mAddress}'", "Block::updateTimestamp" );
+ "' WHERE ipb_address='" . wfStrencode( $this->mAddress ) . "'", "Block::updateTimestamp" );
}
+
}
?>
#$wgPasswordSender = "Wikipedia Mail <apache@www.wikipedia.org>";
$wgPasswordSender = "Wikipedia Mail <apache@www.wikipedia.org>\r\nReply-To: webmaster@www.wikipedia.org";
-
# MySQL settings
#
$wgDBserver = "localhost";
function doSubmit()
{
global $wgOut, $wgUser, $wgLang;
- global $ip, $wpBlockAddress, $wpBlockReason, $wgSysopUserBlocks;
- $fname = "IPBlockForm::doSubmit";
+ global $ip, $wpBlockAddress, $wpBlockReason, $wgSysopUserBans;
$userId = 0;
if ( ! preg_match( "/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/",
$wpBlockAddress ) )
{
- if ( $wgSysopUserBlocks ) {
+ if ( $wgSysopUserBans ) {
$userId = User::idFromName( $wpBlockAddress );
if ( $userId == 0 ) {
$this->showForm( wfMsg( "badipaddress" ) );
}
# Note: for a user block, ipb_address is only for display purposes
-
- $sql = "INSERT INTO ipblocks (ipb_address, ipb_user, ipb_by, " .
- "ipb_reason, ipb_timestamp ) VALUES ('{$wpBlockAddress}', {$userId}, " .
- $wgUser->getID() . ", '" . wfStrencode( $wpBlockReason ) . "','" .
- wfTimestampNow() . "')";
- wfQuery( $sql, $fname );
+ $ban = new Block( $wpBlockAddress, $userId, $wgUser->getID(),
+ wfStrencode( $wpBlockReason ), wfTimestampNow(), 0 );
+ $ban->insert();
$success = wfLocalUrl( $wgLang->specialPage( "Blockip" ),
"action=success&ip={$wpBlockAddress}" );
</form>\n" );
}
-
+
function doSubmit()
{
global $wgOut, $wgUser, $wgLang;
- global $ip, $wpUnblockAddress;
- $fname = "IPUnblockForm::doSubmit";
+ global $wpUnblockAddress;
- $sql = "DELETE FROM ipblocks WHERE ipb_address='{$wpUnblockAddress}'";
- wfQuery( $sql, $fname );
+ $block = new Block();
+
+ if ( $wpUnblockAddress{0} == "#" ) {
+ $block->mId = substr( $wpUnblockAddress, 1 );
+ } else {
+ $block->mAddress = $wpUnblockAddress;
+ }
+
+ $block->delete();
$success = wfLocalUrl( $wgLang->specialPage( "Ipblocklist" ),
- "action=success&ip={$wpUnblockAddress}" );
+ "action=success&ip=" . urlencode($wpUnblockAddress) );
$wgOut->redirect( $success );
}
}
}
-# Callback function
+# Callback function to output a block
function wfAddRow( $block, $tag ) {
global $wgOut, $wgUser, $wgLang, $ip;
$sk = $wgUser->getSkin();
- $addr = $block->mAddress;
+
+ # Hide addresses blocked by User::spreadBlocks, for privacy
+ $addr = $block->mAuto ? "#{$block->mId}" : $block->mAddress;
+
$name = User::whoIs( $block->mBy );
$ulink = $sk->makeKnownLink( $wgLang->getNsText( Namespace::getUser() ). ":{$name}", $name );
$d = $wgLang->timeanddate( $block->mTimestamp, true );
$line = str_replace( "$1", $d, wfMsg( "blocklistline" ) );
$line = str_replace( "$2", $ulink, $line );
- $line = str_replace( "$3", $block->mAddress, $line );
+ $line = str_replace( "$3", $addr, $line );
$wgOut->addHTML( "<li>{$line}" );
- $clink = "<a href=\"" . wfLocalUrlE( $wgLang->specialPage(
- "Contributions" ), "target={$addr}" ) . "\">" .
- wfMsg( "contribslink" ) . "</a>";
- $wgOut->addHTML( " ({$clink})" );
+
+ if ( !$block->mAuto ) {
+ $clink = "<a href=\"" . wfLocalUrlE( $wgLang->specialPage(
+ "Contributions" ), "target={$block->mAddress}" ) . "\">" .
+ wfMsg( "contribslink" ) . "</a>";
+ $wgOut->addHTML( " ({$clink})" );
+ }
if ( $wgUser->isSysop() ) {
$ublink = "<a href=\"" . wfLocalUrlE( $wgLang->specialPage(
- "Ipblocklist" ), "action=unblock&ip={$addr}" ) . "\">" .
+ "Ipblocklist" ), "action=unblock&ip=" . urlencode( $addr ) ) . "\">" .
wfMsg( "unblocklink" ) . "</a>";
$wgOut->addHTML( " ({$ublink})" );
}
{
if ( -1 != $this->mBlockedby ) { return; }
- $ban = new Ban();
- if ( $ban->load( getenv( "REMOTE_ADDR" ), $this->mId ) ) {
+ $block = new Block();
+ if ( !$block->load( getenv( "REMOTE_ADDR" ), $this->mId ) ) {
+ wfDebug( getenv( "REMOTE_ADDR" ) ." is not blocked\n" );
$this->mBlockedby = 0;
return;
}
- $this->mBlockedby = $ban->by;
- $this->mBlockreason = $ban->reason;
+ $this->mBlockedby = $block->mBy;
+ $this->mBlockreason = $block->mReason;
}
function isBlocked()
return;
}
- # Make a new ban object with the desired properties
+ # Make a new block object with the desired properties
wfDebug( "Autoblocking {$this->mUserName}@{$addr}\n" );
$ipblock->mAddress = $addr;
$ipblock->mUser = 0;
$ipblock->mReason = str_replace( "$1", $this->getName(), wfMsg( "autoblocker" ) );
$ipblock->mReason = str_replace( "$2", $userblock->mReason, $ipblock->mReason );
$ipblock->mTimestamp = wfTimestampNow();
+ $ipblock->mAuto = 1;
# Insert it
$ipblock->insert();
$handle = opendir( $source );
while ( false !== ( $f = readdir( $handle ) ) ) {
if ( "." == $f{0} ) continue;
- if ( "CVS" == $f ) continue;
+ # Something made all my "CVSs" go lowercase :(
+ if ( !strcasecmp( "CVS", $f ) ) continue;
copyfile( $source, $f, $dest );
}
}
-- Only UNIQUE keys are defined here; the rest are added by
-- indexes.sql.
--
+-- If you change the main development branch version of this
+-- file, please add an appropriate ALTER TABLE to update.php,
+-- and increment the version number in Version.php.
DROP TABLE IF EXISTS user;
CREATE TABLE user (
DROP TABLE IF EXISTS ipblocks;
CREATE TABLE ipblocks (
+ ipb_id int(8) NOT NULL auto_increment,
ipb_address varchar(40) binary NOT NULL default '',
ipb_user int(8) unsigned NOT NULL default '0',
ipb_by int(8) unsigned NOT NULL default '0',
ipb_reason tinyblob NOT NULL default '',
- ipb_timestamp char(14) binary NOT NULL default ''
+ ipb_timestamp char(14) binary NOT NULL default '',
+ ipb_auto tinyint(1) NOT NULL default '0',
+ UNIQUE KEY ipb_id
) TYPE=MyISAM PACK_KEYS=1;
DROP TABLE IF EXISTS image;
include_once( "{$IP}/Setup.php" );
$wgTitle = Title::newFromText( "Update script" );
$wgCommandLineMode = true;
+$wgAlterSpecs = array();
do_revision_updates();
$handle = opendir( $source );
while ( false !== ( $f = readdir( $handle ) ) ) {
if ( "." == $f{0} ) continue;
- if ( "CVS" == $f ) continue;
+ # Windows turned all my CVS->cvs :(
+ if ( !strcasecmp ( "CVS", $f ) ) continue;
copyfile( $source, $f, $dest );
}
}
}
function do_revision_updates() {
- global $wgSoftwareRevision;
+ global $wgSoftwareRevision, $wgAlterSpecs, $wgDBserver, $wgDBadminuser;
+ global $wgDBadminpassword, $wgDBname;
if ( $wgSoftwareRevision < 1001 ) { update_passwords(); }
+ if ( $wgSoftwareRevision < 1002 ) { alter_ipblocks(); }
+
+ # Run ALTER TABLE queries.
+
+ if ( count( $wgAlterSpecs ) ) {
+ $rconn = mysql_connect( $wgDBserver, $wgDBadminuser, $wgDBadminpassword );
+ mysql_select_db( $wgDBname );
+ print "\n";
+ foreach ( $wgAlterSpecs as $table => $specs ) {
+ $sql = "ALTER TABLE $table $specs";
+ print "$sql;\n";
+ $res = mysql_query( $sql, $rconn );
+ if ( $res === false ) {
+ print "MySQL error: " . mysql_error( $rconn ) . "\n";
+ }
+ }
+ mysql_close( $rconn );
+ }
}
function update_passwords() {
- $fname = "Update scripte: update_passwords()";
+ $fname = "Update script: update_passwords()";
print "\nIt appears that you need to update the user passwords in your\n" .
"database. If you have already done this (if you've run this update\n" .
"script once before, for example), doing so again will make all your\n" .
}
}
+function alter_ipblocks() {
+ global $wgAlterSpecs;
+ $fname = "Update script: alter_ipblocks";
+
+ if ( field_exists( "ipblocks", "ipb_id" ) ) {
+ return;
+ }
+
+ if ( array_key_exists( "ipblocks", $wgAlterSpecs ) ) {
+ $wgAlterSpecs["ipblocks"] .= ",";
+ }
+
+ $wgAlterSpecs["ipblocks"] .=
+ "ADD ipb_auto tinyint(1) NOT NULL default '0', ".
+ "ADD ipb_id int(8) NOT NULL auto_increment,".
+ "ADD PRIMARY KEY (ipb_id)";
+}
+
+function field_exists( $table, $field ) {
+ $fname = "Update script: field_exists";
+ $res = wfQuery( "DESCRIBE $table", $fname );
+ $found = false;
+
+ while ( $row = wfFetchObject( $res ) ) {
+ if ( $row->Field == $field ) {
+ $found = true;
+ break;
+ }
+ }
+ return $found;
+}
+
?>
wfProfileIn( "main-misc-setup" );
OutputPage::setEncodings(); # Not really used yet
+# Useful debug output
+wfDebug( "\nStart request\n" );
+wfDebug( "$REQUEST_METHOD $REQUEST_URI\n" );
+$headers = getallheaders();
+foreach ($headers as $name => $value) {
+ wfDebug( "$name: $value\n" );
+}
+
# Query string fields
#
global $action, $title, $search, $go, $target, $printable;